// 版权归Epic Games, Inc.所有。保留所有权利。

#pragma once

#include "InputModifiers.h"

#include "UObject/UnrealType.h"
#include "LyraInputModifiers.generated.h"

struct FInputActionValue;

class FProperty;
class UEnhancedPlayerInput;
class ULyraAimSensitivityData;
class UObject;

/** 
 * 基于SharedUserSettings中的双精度属性缩放输入
 */
UCLASS(NotBlueprintable, MinimalAPI, meta = (DisplayName = "Setting Based Scalar"))
class ULyraSettingBasedScalar : public UInputModifier
{
	GENERATED_BODY()

public:

	/** 用于钳制此值X轴的属性名称 */
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings)
	FName XAxisScalarSettingName = NAME_None; // X轴缩放设置名称

	/** 用于钳制此值Y轴的属性名称 */
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings)
	FName YAxisScalarSettingName = NAME_None; // Y轴缩放设置名称

	/** 用于钳制此值Z轴的属性名称 */
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings)
	FName ZAxisScalarSettingName = NAME_None; // Z轴缩放设置名称
	
	/** 设置每个轴上此设置的最大值。 */
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings)
	FVector MaxValueClamp = FVector(10.0, 10.0, 10.0); // 最大值钳制向量
	
	/** 设置每个轴上此设置的最小值。 */
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings)
	FVector MinValueClamp = FVector::ZeroVector; // 最小值钳制向量

protected:
	virtual FInputActionValue ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override;

	/** FProperty缓存，将填充在设置类上找到的任何FProperty，这样我们就不需要每帧查找它们 */
	TArray<const FProperty*> PropertyCache; // 属性缓存数组
};

/** 表示此死区是针对哪个摇杆的，移动摇杆或视角摇杆 */
UENUM()
enum class EDeadzoneStick : uint8
{
	/** 移动摇杆的死区 */
	MoveStick = 0, // 移动摇杆

	/** 视角摇杆的死区 */
	LookStick = 1, // 视角摇杆
};

/**
 * 这是一个死区输入修改器，其阈值将由Lyra共享游戏设置中的内容驱动。
 */
UCLASS(NotBlueprintable, MinimalAPI, meta = (DisplayName = "Lyra Settings Driven Dead Zone"))
class ULyraInputModifierDeadZone : public UInputModifier
{
	GENERATED_BODY()

public:

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings, Config)
	EDeadZoneType Type = EDeadZoneType::Radial; // 死区类型，默认为径向死区
	
	// 输入被钳制到1的阈值
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings, Config)
	float UpperThreshold = 1.0f; // 上阈值

	/** 此死区针对哪个摇杆。这控制在计算死区时将使用哪个设置 */
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings, Config)
	EDeadzoneStick DeadzoneStick = EDeadzoneStick::MoveStick; // 死区摇杆类型

protected:
	virtual FInputActionValue ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override;

	// 未修改时显示为黑色。被阻止时显示为红色（使用不同的强度表示轴）
	// 镜像https://www.gamasutra.com/blogs/JoshSutphin/20130416/190541/Doing_Thumbstick_Dead_Zones_Right.php中的可视化。
	virtual FLinearColor GetVisualizationColor_Implementation(FInputActionValue SampleValue, FInputActionValue FinalValue) const override;
};

/** 应考虑的瞄准灵敏度类型 */
UENUM()
enum class ELyraTargetingType : uint8
{
	/** 正常环视时应用的灵敏度 */
	Normal = 0, // 正常瞄准

	/** 瞄准时应用的灵敏度 */
	ADS = 1, // 瞄准瞄准镜
};

/** 根据Lyra共享游戏设置中的当前游戏手柄设置应用标量修改器。 */
UCLASS(NotBlueprintable, MinimalAPI, meta = (DisplayName = "Lyra Gamepad Sensitivity"))
class ULyraInputModifierGamepadSensitivity : public UInputModifier
{
	GENERATED_BODY()
public:
	
	/** 用于此灵敏度的瞄准类型 */
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category=Settings, Config)
	ELyraTargetingType TargetingType = ELyraTargetingType::Normal; // 瞄准类型

	/** 资产，使我们能够访问用于灵敏度的浮点标量值 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta=(AssetBundles="Client,Server"))
	TObjectPtr<const ULyraAimSensitivityData> SensitivityLevelTable; // 灵敏度级别表

protected:
	virtual FInputActionValue ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override;
};

/** 根据Lyra共享游戏设置中的设置应用轴值反转 */
UCLASS(NotBlueprintable, MinimalAPI, meta = (DisplayName = "Lyra Aim Inversion Setting"))
class ULyraInputModifierAimInversion : public UInputModifier
{
	GENERATED_BODY()
	
protected:
	virtual FInputActionValue ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override;	
};